#include "head.h"

extern struct order_t order;
int login_user(int netfd,const char* name,const char* passwd)
{
    printf("enter login\n");
    bzero(&order,sizeof(order));
    train_t train;
    order.order=LOGIN;
    strcpy(order.dir,passwd);
    strcpy(order.name,name);
    send(netfd,&order,sizeof(order),0);
    printf("send success\n");

    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
        printf("username or passwd error!\n");
        exit_client(netfd);
        exit(-1);
    }
    else
    {
        printf("LOGIN SUCCESS!\n");
        return 0;
    }
}

int cd_dir(int netfd,const char*dir)
{
    bzero(&order, sizeof(order));
    train_t train;
    order.order=CD;
    strcpy(order.dir,dir);
    send(netfd,&order,sizeof(order),0);
    
    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
        printf("cd,fault!\n");
        printf("%s\n",train.data);
    }
	else if(train.length==0)
{
printf("%s\n",train.data);
}

    return 0;
}

int ls_dir(int netfd)
{
    bzero(&order, sizeof(order));
    train_t train;
    order.order=LS;
    send(netfd,&order,sizeof(order),0);
    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
	printf("ls:fault!\n");
        printf("%s\n",train.data);
    }
    else if(train.length==0)
    {
	printf("ls:");
        printf("%s\n",train.data);
    }
    return 0;
}

int puts_file(int netfd,const char* name,const char* dir)
{
    bzero(&order, sizeof(order));
    order.order=PUTS;
    strcpy(order.name,name);
    strcpy(order.dir,dir);
    send(netfd,&order,sizeof(order),0);
    
    train_t train;
    //接收服务端文件报错
    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
        printf("%s\n",train.data);
        return -1;
    }

    memset(&train,0,sizeof(train_t));
    train.length=strlen(name);
    memcpy(train.data,name,train.length);
    send(netfd,&train,sizeof(int)+train.length,MSG_NOSIGNAL);   //发送文件名

    int fd=open(name,O_RDWR);
    struct stat statbuf;
    fstat(fd,&statbuf);
    train.length=sizeof(statbuf.st_size);
    memcpy(train.data,&statbuf.st_size,train.length);
    send(netfd,&train,sizeof(int)+train.length,MSG_NOSIGNAL);   //发送文件大小

    if(statbuf.st_size<100*1024*1024)
    {
        while(1){
            bzero(&train,sizeof(train));
            ssize_t sret=read(fd,train.data,sizeof(train.data));
            train.length=sret;
            send(netfd,&train,sizeof(train),MSG_NOSIGNAL);
            if(sret==0)
            {
                break;
            }
        }
    }
    else
    {
        char *p=(char*)mmap(NULL,statbuf.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
        ERROR_CHECK(p,MAP_FAILED,"mmap");
        off_t totalsize=0;
        while(totalsize<statbuf.st_size)
        {
            if(statbuf.st_size-totalsize>1000)
            {
                train.length=1000;
            }
            else
            {
                train.length=statbuf.st_size-totalsize;
            }
            send(netfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
            send(netfd,p+totalsize,train.length,MSG_NOSIGNAL);
            totalsize+=train.length;
        }
        train.length=0;
        send(netfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
        munmap(p,statbuf.st_size);
    }
    close(fd);
    printf("puts success!\n");
    return 0;
}   

int gets_file(int netfd,const char* name,const char* dir)
{
    bzero(&order, sizeof(order));
    order.order=GETS;
    strcpy(order.name,name);
    strcpy(order.dir,dir);
    send(netfd,&order,sizeof(order),0);

    train_t train;
    //接收服务端文件报错
    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
        printf("%s\n",train.data);
        return -1;
    }

    int fd=open(name,O_RDWR|O_CREAT,0666);
    struct stat statbuf;
    fstat(fd,&statbuf);
    train.length=sizeof(statbuf.st_size);
    memcpy(train.data,&statbuf.st_size,train.length);
    send(netfd,&train,sizeof(int)+train.length,MSG_NOSIGNAL);   //发送本地已有的文件大小
    
    int length;
    off_t filesize=0;       //直接接收服务器文件大小
    recvn(netfd,&length,sizeof(length));
    recvn(netfd,&filesize,length);

    //接收文件内容
    off_t cursize=statbuf.st_size;
    off_t slice=filesize/10000;
    off_t lastsize=cursize;
    if(filesize<100*1024*1024)
    {
        while(1)
        {
            char buf[4096]={0};
            recvn(netfd,&length,sizeof(length));
            if(length!=1000)
            {
                printf("length=%d\n",length);
            }
            if(length==0)
            {
                break;
            }
            recvn(netfd,buf,length);
            write(fd,buf,length);
            cursize+=length;
            if(cursize-lastsize>slice)
            {
                printf("%5.2lf%%\r",100.0*cursize/filesize);
                fflush(stdout);
                lastsize=cursize;
            }
        }
        printf("100.00%%\n");
	printf("gets success!\n");
        close(fd);
    }
    else
    {
        ftruncate(fd,filesize);
        char *p=(char*)mmap(NULL,filesize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
        ERROR_CHECK(p,MAP_FAILED,"mmap");
        recvn(netfd,p,filesize);
        munmap(p,filesize);
        printf("100.00%%\n");
	printf("gets success!\n");
        close(fd);
        return 0;
    }
}

int remove_file(int netfd,const char* name,const char* dir)
{
    bzero(&order, sizeof(order));
    train_t train;
    order.order=REMOVE;
    strcpy(order.name,name);
    strcpy(order.dir,dir);
    send(netfd,&order,sizeof(order),0);

    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
	    printf("remove fault!\n");
        printf("%s\n",train.data);
    }
    return 0;
}

int pwd(int netfd)
{
    bzero(&order, sizeof(order));
    train_t train;
    order.order=PWD;
    send(netfd,&order,sizeof(order),0);

    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
	printf("pwd fault!\n");
        printf("%s\n",train.data);
    }
    else if(train.length==0)
    {
        printf("%s\n",train.data);
    }
    return 0;
}

int mkdir_dir(int netfd,const char* name,const char* dir)
{
    bzero(&order, sizeof(order));
    train_t train;
    order.order=MKDIR;
    strcpy(order.name,name);
    strcpy(order.dir,dir);
    send(netfd,&order,sizeof(order),0);

    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
	printf("mkdir fault!\n");
        printf("%s\n",train.data);
    }
    return 0;
}

int rmdir_dir(int netfd,const char* name,const char* dir)
{
    bzero(&order, sizeof(order));
    train_t train;
    order.order=RMDIR;
    strcpy(order.name,name);
    strcpy(order.dir,dir);
    send(netfd,&order,sizeof(order),0);

    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
	    printf("rmdir fault!\n");
        //printf("%s\n",train.data);
    }
    return 0;
}

int exit_client(int netfd)
{
    bzero(&order, sizeof(order));
    train_t train;
    order.order=EXIT;
    send(netfd,&order,sizeof(order),0);

    recvn(netfd,&train,sizeof(train));
    if(train.length==-1)
    {
        printf("%s\n",train.data);
    }
    else if(train.length==0)
    {
        printf("EXIT SUCCESS!\n");
        exit(0);
    }
    return 0;
}

int recvn(int sockfd, void *buf, int length){
    int total = 0;
    char *p = (char *)buf;
    while(total < length){
        ssize_t sret = recv(sockfd,p+total,length-total,0);
        total += sret;
    }
    return total;
}
